package com.sicau.smarttraceplatform.utils;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import org.springframework.util.StringUtils;

import java.lang.annotation.*;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.stream.Stream;

/**
 * @Author sxt
 * @Date 2020.04.05
 */
public class QueryWrapperUtil {
    /**
     * 封装查询wrapper
     *
     * @param targetType QueryWrapper的目标类型
     * @param paramClass 参数类型
     * @param param 参数对象
     * @param <T> QueryWrapper的目标类类型
     * @param <E> 参数类类型
     * @return {@link QueryWrapper}
     */
    public static <T, E> QueryWrapper<T> getQueryWrapper(Class<T> targetType, Class<E> paramClass, E param) {
        if (targetType == null || paramClass == null || param == null) {
            return null;
        }
        QueryWrapper<T> queryWrapper = new QueryWrapper<>();
        Method[] declaredMethods = paramClass.getDeclaredMethods();
        Stream<Method> getMethods = Arrays.stream(declaredMethods).filter(item -> item.getName().startsWith("get"));
        getMethods.forEach(item -> {
            String methodName = item.getName();
            String tmp = methodName.substring(methodName.indexOf("get") + "get".length());
            String fieldName = tmp.substring(0, 1).toLowerCase() + tmp.substring(1);/*首字母转小写*/
            String column = getColumn(paramClass, fieldName);
            if (column != null) {
                Object rs = null;
                try {
                    rs = item.invoke(param);
                } catch (IllegalAccessException | InvocationTargetException e) {
                    e.printStackTrace();
                }
                if (!StringUtils.isEmpty(rs)) {
                    if (isFieldHasAnnotation(fieldName, paramClass, NeedLike.class)) {
                        queryWrapper.like(column, rs);
                    } else {
                        queryWrapper.eq(column, rs);
                    }
                }
            }
        });

        return queryWrapper;
    }

    /**
     *
     * @param paramClass 需要解析的类
     * @param fieldName 属性名称
     * @param <E> 需要解析的类类型
     * @return 字段对应的column名
     */
    private static <E> String getColumn(Class<E> paramClass, String fieldName) {
        if(isFieldHasAnnotation(fieldName, paramClass, Ignore.class)){
            return null;
        }
        String column = null;
        Field field = null;
        try {
            field = paramClass.getDeclaredField(fieldName);
        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        }
        if (field != null) {
            Column annotation = field.getAnnotation(Column.class);
            if (annotation != null) {
                column = annotation.column();
            } else {
                column = UnderlineWithHump.HumpToUnderline(fieldName);
            }
        }
        return column;
    }

    /**
     * 判断一个类的字段是否标有某个特定的注解
     *
     * @param fieldName   字段名
     * @param tClass      目标检测类
     * @param tAnnotation 目标检测注解类
     * @return 布尔值
     */
    private static <T, E extends Annotation> boolean isFieldHasAnnotation(String fieldName, Class<T> tClass, Class<E> tAnnotation) {
        Field targetField = null;
        try {
            targetField = tClass.getDeclaredField(fieldName);
        } catch (NoSuchFieldException e) {
            return false;
        }
        E needLike = (E) targetField.getAnnotation(tAnnotation);

        return needLike != null;
    }


    /**
     * 用来标记是否需要使用Like关键字
     */
    @Target({ElementType.FIELD})
    @Retention(RetentionPolicy.RUNTIME)
    public @interface NeedLike {

    }

    /**
     * 用来标记column的名字
     */
    @Target({ElementType.FIELD})
    @Retention(RetentionPolicy.RUNTIME)
    public @interface Column {
        String column() default "";
    }

    /**
     * 用来标记是否需要忽略
     */
    @Target({ElementType.FIELD})
    @Retention(RetentionPolicy.RUNTIME)
    public @interface Ignore {

    }
}
